package com.bruce.tool.orm.mybatis.generator.plugin;

import com.google.common.collect.Lists;
import org.mybatis.generator.api.GeneratedXmlFile;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.springframework.util.CollectionUtils;

import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * 注解方式:生成Dao
 * 功能 : 
 * 1.继承CRUD接口
 * 2.增加包扫描注解
 * 3.清除原有接口自带的方法
 * @author : Bruce(刘正航) 11:57 2019-05-11
 */
public class AnnotationMapperPlugin extends PluginAdapter {

    private final List<String> imports = Lists.newArrayList(
            "org.apache.ibatis.annotations.Mapper",
            "com.bruce.tool.orm.mybatis.core.mapper.BaseMapper",
            "org.springframework.stereotype.Component"
    );

    private final List<String> generatedKeysImports = Lists.newArrayList(
            "com.bruce.tool.orm.mybatis.core.provider.SaveProvider",
            "org.apache.ibatis.annotations.InsertProvider",
            "org.apache.ibatis.annotations.Options"
    );

    /**表主键常量**/
    private static final String ID = "id";

    private final List<String> annotations = Lists.newArrayList("@Mapper","@Component");

    private static final String INTERFACE_MAPPER = "BaseMapper";

    @Override
    public boolean validate(final List<String> warnings) {
        return true;
    }

    @Override
    public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
        return false;
    }

    /**生成实体**/
    @Override
    public boolean clientGenerated(Interface interfaze, IntrospectedTable introspectedTable) {
        // 清空所有方法(getter/setter方法)
        interfaze.getMethods().clear();
        clearUnnecessaryImport(interfaze);
        interfaze.addImportedType(new FullyQualifiedJavaType(introspectedTable.getBaseRecordType()));
        interfaze.addSuperInterface(new FullyQualifiedJavaType(INTERFACE_MAPPER+"<"+new FullyQualifiedJavaType(introspectedTable.getBaseRecordType()).getShortName()+">"));
        for (String needImport : imports) {
            interfaze.addImportedType(new FullyQualifiedJavaType(needImport));
        }
        for (String annotation : annotations) {
            interfaze.addAnnotation(annotation);
        }
        List<IntrospectedColumn> columns = introspectedTable.getPrimaryKeyColumns();
        if(!CollectionUtils.isEmpty(columns) && columns.size() == 1){
            IntrospectedColumn column = columns.get(0);
            String primaryKey = column.getActualColumnName();
            // 数据库表主键不是"id",则需要额外生成save方法,指定主键
            if( !ID.equals(primaryKey) ){
                createSpecialSaveMethod(interfaze, introspectedTable, column, primaryKey, "save");
                createSpecialSaveMethod(interfaze, introspectedTable, column, primaryKey, "saveBySelective");
            }
        }
        return true;
    }

    /**创建特殊的save方法**/
    private void createSpecialSaveMethod(Interface interfaze, IntrospectedTable introspectedTable, IntrospectedColumn column, String primaryKey, String methodName) {
        for (String needImport : generatedKeysImports) {
            interfaze.addImportedType(new FullyQualifiedJavaType(needImport));
        }
        Method method = new Method(methodName);
        method.setAbstract(true);
        method.setReturnType(new FullyQualifiedJavaType("java.lang.Integer"));
        Parameter parameter = new Parameter(new FullyQualifiedJavaType(introspectedTable.getBaseRecordType()),"domain");
        method.addParameter(parameter);
        method.addAnnotation("@Override");
        method.addAnnotation("@InsertProvider(type = SaveProvider.class, method = \""+methodName+"\")");
        String primaryField = column.getJavaProperty();
        method.addAnnotation("@Options(useGeneratedKeys = true,keyColumn = \""+primaryKey+"\",keyProperty = \""+primaryField+"\")");
        interfaze.addMethod(method);
    }

    /**清除无用的引入**/
    private void clearUnnecessaryImport(Interface interfaze) {
        Set<FullyQualifiedJavaType> importedTypes = interfaze.getImportedTypes();
        Iterator<FullyQualifiedJavaType> iter = importedTypes.iterator();
        List<FullyQualifiedJavaType> needRemove = Lists.newArrayList();
        while (iter.hasNext()){
            FullyQualifiedJavaType javaType = iter.next();
            if("List".equals(javaType.getShortName())){
                needRemove.add(javaType);
            }
            if("Param".equals(javaType.getShortName())){
                needRemove.add(javaType);
            }
            if(javaType.getShortName().contains("Example")){
                needRemove.add(javaType);
            }
        }
        for (FullyQualifiedJavaType javaType : needRemove){
            importedTypes.remove(javaType);
        }
    }

}
